﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using PagedList;

namespace YuFeng.Repositories
{
    public class Page
    {
        public int PageNumber { get; set; }
        public int PageSize { get; set; }

        public Page()
        {
            PageNumber = 1;
            PageSize = RepositoryOptions.DefaultPageSize;
        }

        public Page(int pageNumber, int pageSize)
        {
            PageNumber = pageNumber;
            PageSize = pageSize;
        }

        public int Skip
        {
            get { return (PageNumber - 1) * PageSize; }
        }
    }

    public static class PagingExtensions
    {
        /// <summary>
        /// Extend IQueryable to simplify access to skip and take methods 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="page"></param>
        /// <returns>IQueryable with Skip and Take having been performed</returns>
        public static IQueryable<T> GetPage<T>(this IQueryable<T> queryable, Page page)
        {
            return queryable.Skip(page.Skip).Take(page.PageSize);
        }
        public static IEnumerable<T> GetPage<T>(this IEnumerable<T> queryable, Page page)
        {
            return queryable.Skip(page.Skip).Take(page.PageSize);
        }
        public static IPagedList<T> GetPage<T, TOrder>(this IQueryable<T> queryable
            , Expression<Func<T, bool>> where, Expression<Func<T, TOrder>> order, Page page
            , bool isOrderDesc = false)
        {
            IQueryable<T> results;
            if (isOrderDesc)
                results = queryable.Where(where).OrderByDescending(order).GetPage(page);
            else
                results = queryable.Where(where).OrderBy(order).GetPage(page);
            var total = queryable.Count(where);
            return new StaticPagedList<T>(results, page.PageNumber, page.PageSize, total);
        }
        public static IPagedList<T> GetPage<T, TOrder>(this IQueryable<T> queryable
            , Expression<Func<T, bool>> where, Expression<Func<T, TOrder>> order
            , int pageNumber = 1
            , int pageSize = RepositoryOptions.DefaultPageSize
            , bool isOrderDesc = false)
        {
            Page page = new Page()
            {
                PageNumber = pageNumber,
                PageSize = pageSize
            };
            return queryable.GetPage<T, TOrder>(where, order, page, isOrderDesc);
        }
        public static IPagedList<T> GetPage<T, TOrder>(this IQueryable<T> queryable
            , Expression<Func<T, TOrder>> order
            , Page page
            , bool isOrderDesc = false)
        {
            IQueryable<T> results;
            if (isOrderDesc)
                results = queryable.OrderByDescending(order).GetPage(page);
            else
                results = queryable.OrderBy(order).GetPage(page);
            var total = queryable.Count();
            return new StaticPagedList<T>(results, page.PageNumber, page.PageSize, total);
        }

        public static IPagedList<T> GetPage<T, TOrder>(this IQueryable<T> queryable
            , Expression<Func<T, TOrder>> order
            , int pageNumber = 1
            , int pageSize = RepositoryOptions.DefaultPageSize
            , bool isOrderDesc = false)
        {
            Page page = new Page()
            {
                PageNumber = pageNumber,
                PageSize = pageSize
            };
            return queryable.GetPage<T, TOrder>(order, page, isOrderDesc);
        }
    }
}
